home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / ptc.zip / PTOC.DOC < prev   
Text File  |  1988-02-06  |  58KB  |  1,830 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                _P_T_C _i_m_p_l_e_m_e_n_t_a_t_i_o_n _n_o_t_e
  19.  
  20.                                          by
  21.  
  22.                                     Per Bergsten
  23.  
  24.                                Holistic Technology AB
  25.                                    Grona Gatan 59
  26.                                   414 54 Gothenburg
  27.                                        Sweden
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.           This note describes the implementation of  ptc,  a  Pascal  to  C
  42.           translator.   The program was developed by Per Bergsten of Holis-
  43.           tic Technology AB, Gothenburg, Sweden.  The paper is intended  to
  44.           provide  a  guide  for  those  who need to transport ptc to a new
  45.           environment, it describes how Pascal constructs are mapped onto C
  46.           constructs.
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  71.  
  72.           _1.  _B_a_c_k_g_r_o_u_n_d
  73.  
  74.           The aim was originally to provide a simple tool for  transporting
  75.           finished  applications  to systems lacking Pascal compilers.  The
  76.           first versions,  constructed  in  about  1984,  were  capable  of
  77.           translating  simple  Pascal  programs.   It was never intended to
  78.           become a released product, however, as time went by, programs and
  79.           ambitions grew to the point where nearly the full Pascal language
  80.           was supported.  Thus the program as it stands today  has  a  long
  81.           ancestry  but  it has never been redesigned (which it should have
  82.           been).
  83.  
  84.           _2.  _P_a_s_c_a_l _v_s _C
  85.  
  86.           To anyone familiar with the two languages it is obvious that they
  87.           are very similar in structure.  The major features may be summar-
  88.           ised as follows:
  89.  
  90.                      Pascal                            C
  91.  
  92.           Block-structured                Block-structured
  93.           - multiple declaration levels   - single declaration level
  94.           Statically scoped               Statically scoped
  95.           Strongly typed                  Weakly typed
  96.                                           - allows unbounded pointers
  97.           Call by value                   Mostly call by value
  98.           - and call by reference
  99.           Highly independent              Highly integrated
  100.           - of host system                - with system
  101.           Self contained                  Allows external definitions.
  102.  
  103.  
  104.           On the syntactic level the languages differ only in  minor  ways,
  105.           mostly  in  the  order in which keywords and other symbols occur,
  106.           and of course in that the languages uses  different  symbols  for
  107.           the  same  purposes.   The  only complication is that C prohibits
  108.           nested subroutine declarations.
  109.  
  110.           On the semantic level the situation is worse.  C  has  the  pecu-
  111.           liarity  that  array variables are treated differently from other
  112.           variables, this forces us to adopt some  general  way  to  handle
  113.           array variables.  Furthermore, since Pascal offers nested subrou-
  114.           tine declarations it becomes necessary to simulate  part  of  the
  115.           activation  record  mechanism in the translated code, in one case
  116.           it is extremely difficult to completely  do  this.   It  is  also
  117.           clear  that  the  C  typedef mechanism has some shortcomings that
  118.           preclude an easy translation of Pascal types.
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.                                         - 1 -
  134.  
  135.  
  136.  
  137.  
  138.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  139.  
  140.           _3.  _M_a_p_p_i_n_g _P_a_s_c_a_l _t_o _C
  141.  
  142.           In this part of the paper we briefly illustrate how to  translate
  143.           Pascal code into equivalent C code.
  144.  
  145.           _3._1.  _P_r_o_g_r_a_m_s
  146.  
  147.           A minimal Pascal program:
  148.  
  149.                   program p;
  150.                   begin
  151.                   end.
  152.  
  153.           translates to the C equivalent:
  154.  
  155.                   extern void exit();
  156.                   main()
  157.                   {
  158.                           exit(0);
  159.                   }
  160.  
  161.  
  162.           It should be noted here that the  translator  does  not  actually
  163.           require  a  complete  Pascal  program, the implementation is such
  164.           that any consistent set of declarations can be translated.
  165.  
  166.           _3._2.  _L_e_x_i_c_a_l _i_s_s_u_e_s
  167.  
  168.           The C language uses ASCII as a carrier, almost all of the availi-
  169.           ble  characters  are  used.  The Pascal definition uses a smaller
  170.           set of characters.  Since few features of the languages depend on
  171.           the  underlying character set this does not introduce much diffi-
  172.           culties.
  173.  
  174.           One serious problem does occur.  Both language definitions states
  175.           that  comments have no meaning and no clear place in the language
  176.           syntax.  Furthermore, the Pascal definition states that a comment
  177.           is  equivalent  to  a blank character.  This implies that if com-
  178.           ments are handled accurately the translator should also  be  able
  179.           to  collect and classify each blank character in a Pascal program
  180.           and to generate a C program with the same number of blank charac-
  181.           ters  in the corresponding positions.  This implication conflicts
  182.           with the fact that the languages have different syntax rules,  it
  183.           is not obvious what the "corresponding positions" would be.
  184.  
  185.           Since comments have no defined meaning a user is free  to  inter-
  186.           pret  them  in any way and, in particular, to associate them with
  187.           the surrounding code in any way s/he  chooses.   Although  humans
  188.           usually are able to deduce what bearing a comment has on the sur-
  189.           rounding program code there are no formal rules  for  how  to  do
  190.           this.   Therefore  there  is no _a _p_r_i_o_r_i correct way to translate
  191.           comments and the translator described here ignores comments alto-
  192.           gether.   If/when  a  reasonable  _a_d  _h_o_c  solution is found that
  193.           feature may be incorporated.
  194.  
  195.           _3._3.  _D_e_c_l_a_r_a_t_i_o_n_s
  196.  
  197.           The program may introduce local declarations which are handled as
  198.           follows.
  199.  
  200.  
  201.  
  202.  
  203.                                         - 2 -
  204.  
  205.  
  206.  
  207.  
  208.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  209.  
  210.           _3._3._1.  _L_a_b_e_l_s
  211.  
  212.  
  213.                   program p;
  214.  
  215.                   label 9;
  216.  
  217.                   begin
  218.                   9:
  219.                           goto 9
  220.                   end.
  221.  
  222.           which we simply translate into:
  223.  
  224.                   extern void exit();
  225.                   main()
  226.                   {
  227.                   L9:
  228.                           goto L9;
  229.                           exit(0);
  230.                   }
  231.  
  232.  
  233.           If the label is reached from an inner procedure:
  234.  
  235.                   program p;
  236.  
  237.                   label 100;
  238.  
  239.                           procedure q;
  240.  
  241.                           begin
  242.                                   goto 100
  243.                           end;
  244.  
  245.                   begin
  246.                   100:
  247.                   end.
  248.  
  249.           a more complicated translation must be used:
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.                                         - 3 -
  272.  
  273.  
  274.  
  275.  
  276.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  277.  
  278.                   # define Line __LINE__
  279.                   void Caseerror();
  280.                   # include <setjmp.h>
  281.                   static struct Jb { jmp_buf jb; } J[1];
  282.  
  283.                    void
  284.                   q()
  285.                   {
  286.                           longjmp(J[0].jb, 100);
  287.                   }
  288.  
  289.                   main()
  290.                   {
  291.                           if (setjmp(J[0].jb))
  292.                                   goto L100;
  293.                   L100:
  294.                           exit(0);
  295.                   }
  296.  
  297.  
  298.           We assume the existence of the standard  _s_e_t_j_m_p()  and  _l_o_n_g_j_m_p()
  299.           library  functions.   Jumpbuffers  are  statically  allocated  as
  300.           needed depending on the number of declarationlevels in  the  pro-
  301.           gram.
  302.  
  303.           _3._3._2.  _C_o_n_s_t_a_n_t_s
  304.  
  305.           Constant declarations are treated in two different ways.  Numbers
  306.           aliases  etc  are simply # _d_e_f_i_n_e'd but string constants are con-
  307.           verted to static character arrays in order to  avoid  unnecessary
  308.           duplication of string-constants in the object code, thus:
  309.  
  310.                   const
  311.                      p  = 3.14;
  312.                      pie   = '3.14';
  313.  
  314.           translates to:
  315.  
  316.                   # define pi 3.14
  317.                   static char pie[] = "3.14";
  318.  
  319.  
  320.           _3._3._3.  _T_y_p_e_s _a_n_d _v_a_r_i_a_b_l_e_s
  321.  
  322.           Types and variables are mostly easy to translate:
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.                                         - 4 -
  339.  
  340.  
  341.  
  342.  
  343.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  344.  
  345.                   program p;
  346.  
  347.                   const length   = 15;
  348.  
  349.                   type
  350.                      struct      = 0 .. length;
  351.                      vect     = array [ struct ] of struct;
  352.                      color    = (red, blue, ada, yellow);
  353.                      pointer  = ^ recd;
  354.                      recd     = record
  355.                               r  : pointer;
  356.                               case b : boolean of
  357.                                 false: (c : color);
  358.                                 true:  (v : vect);
  359.                              end;
  360.  
  361.                   var   SP    : pointer;
  362.  
  363.                   begin
  364.                      new(SP, true);
  365.                   end.
  366.  
  367.           becomes
  368.  
  369.                   typedef char    boolean;
  370.                   # define false (boolean)0
  371.                   # define true (boolean)1
  372.                   extern char *Bools[];
  373.                   # define Unionoffs(p, m) (((long)(&(p)->m))-((long)(p)))
  374.                   extern char *malloc();
  375.                   # define length 15
  376.                   typedef unsigned char C47_struct;
  377.                   typedef struct { C47_struct A[length + 1]; } vect;
  378.                   typedef enum { red, blue, ada, yellow } color;
  379.                   typedef struct S57 *pointer;
  380.                   typedef struct S57 {
  381.                      pointer  r;
  382.                      boolean  b;
  383.                      union {
  384.                         struct {
  385.                            color    c;
  386.                         } V1;
  387.                         struct  {
  388.                            vect  v;
  389.                         } V2;
  390.                      } U;
  391.                   }  recd;
  392.                   pointer  sp;
  393.  
  394.                   main()
  395.                   {
  396.                      sp = (struct S57 *)malloc((unsigned)
  397.                         (Unionoffs(sp, U.V2.v) + sizeof(sp->U.V2)));
  398.                      exit(0);
  399.                   }
  400.  
  401.           The rationale is as follows:
  402.  
  403.  
  404.  
  405.                                         - 5 -
  406.  
  407.  
  408.  
  409.  
  410.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  411.  
  412.           Identifiers in the Pascal program which conflicts  with  reserved
  413.           words  in  C are renamed by adding a unique prefix Cnnn where nnn
  414.           is a number.
  415.  
  416.           We also note here that uppercase letters in identifiers and  key-
  417.           words   are  translated  to  lowercase.   Pascal  specifies  that
  418.           upper/lower case is insignificant whereas  C  (for  the  present)
  419.           separates  the two.  This fact is used to advantage by the trans-
  420.           lator as all subroutines and macros  defined  by  the  translator
  421.           have an initial uppercase letter which prevents confusion.
  422.  
  423.           -    The type _b_o_o_l_e_a_n is a predefined Pascal  type,  when  it  is
  424.                used  the  translator emits code which defines boolean to be
  425.                the smallest convenient type: _c_h_a_r.  The constants _f_a_l_s_e and
  426.                _t_r_u_e  are  defined  and  the vector _B_o_o_l_s will contain text-
  427.                strings for output if needed.
  428.  
  429.           -    The predefined types _i_n_t_e_g_e_r and _r_e_a_l  are  likewise  mapped
  430.                directly  onto the standard C types _i_n_t and _d_o_u_b_l_e through a
  431.                typedef declaration.
  432.  
  433.                Integer subranges are  mapped  onto  standard  C  arithmetic
  434.                types  according  to  a  short table in the translator.  The
  435.                table is scanned from top to bottom until an enclosing range
  436.                is found and the corresponding type-name is emitted.
  437.  
  438.           -    C-arrays have peculiar semantix.  To unify the treatment  of
  439.                arrays and other datatypes we always encapsulate an array in
  440.                a struct, thus an array always becomes a _s_t_r_u_c_t with a  sin-
  441.                gle member named A.
  442.  
  443.           -    Records and their variants are translated into C _s_t_r_u_c_t  and
  444.                _u_n_i_o_n  definitions.   Since  C requires all union members to
  445.                have a name we must supply artificial names for  all  record
  446.                variants.  A record with variants will therefore always con-
  447.                tain one field with the name U which have  sub-fields  named
  448.                Vnnn where nnn is a positive number.
  449.  
  450.                When allocating dynamic storage for a record  with  variants
  451.                naming the desired variant
  452.  
  453.                        new(sp, true)
  454.  
  455.                we face the problem of  determining  the  amount  of  memory
  456.                needed.
  457.  
  458.                _C _d_o_e_s _n_o_t _p_r_o_v_i_d_e _a _s_a_f_e _w_a_y _t_o _c_o_m_p_u_t_e _t_h_e _s_i_z_e _o_f  _a
  459.                _p_a_r_t_i_c_u_l_a_r _s_t_r_u_c_t _v_a_r_i_a_n_t.
  460.  
  461.                The strategy adopted to cope with this problem is to attempt
  462.                to compute the offset of a fieldmember in the variant match-
  463.                ing the constant and then to add the size  of  the  variant.
  464.                The  offset  computation is expressed as a macro, _U_n_i_o_n_o_f_f_s,
  465.                which uses rather foul typecasting  to  achive  the  result.
  466.                The only availible alternative would be to use the same size
  467.                of all variants.  This  method,  while  being  safe,  wastes
  468.                memory  when  many  small  and few large records of the same
  469.                type are created dynamically.
  470.  
  471.  
  472.  
  473.                                         - 6 -
  474.  
  475.  
  476.  
  477.  
  478.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  479.  
  480.           -    Pascal enumeration types are converted directly  to  C  _e_n_u_m
  481.                types.
  482.  
  483.           -    Pascal pointer types are translated into  C  pointer  types.
  484.                Pascal allows the programmer to construct recursive types as
  485.                pointer types need not be fully defined until the end of the
  486.                declaration-section  where  the  pointer  type  is used.  In
  487.                practice this is only used to introduce record  types  which
  488.                contain  pointers  to themselves.  This problem is partially
  489.                solved by introducing a name for the record type.  Hence
  490.  
  491.                        type
  492.                           ptr   = ^ node;
  493.                           node  = record
  494.                                 next  : ptr;
  495.                                 info  : integer
  496.                                end;
  497.  
  498.                becomes
  499.  
  500.                        typedef struct S56 * ptr;
  501.                        typedef struct S56 {
  502.                           ptr      next;
  503.                           integer     info;
  504.                        } node;
  505.  
  506.                we note in passing that the  problem  cannot  be  completely
  507.                solved since
  508.  
  509.                        type  pureptr  = ^ pureptr;
  510.  
  511.                which is valid Pascal, cannot be expressed in C.
  512.  
  513.           -    A pascal set-type does not have any direct counterpart in C.
  514.                The C language does however have a adequate set of operators
  515.                for bit manipulation.  We use these to  implement  a  Pascal
  516.                set as an array of _s_e_t_w_o_r_d.  So:
  517.  
  518.                        type
  519.                           s  = set of 1 .. 100;
  520.  
  521.                        var
  522.                           ss : s;
  523.  
  524.                is translated into:
  525.  
  526.                        typedef unsigned short setword;
  527.                        typedef struct { setword S[8]; } s;
  528.  
  529.                        s  ss;
  530.  
  531.                The situation is slightly complicated by the fact that  Pas-
  532.                cal  has a set constructor which permits the construction of
  533.                arbitrary large sets, for example:
  534.  
  535.                        s := [ 50 .. maxint ] * [ 1 .. 80 ]
  536.  
  537.                for that reason the first member in the array of words gives
  538.                size  of  the  set  (in words).  In the example above s.S[0]
  539.  
  540.  
  541.  
  542.  
  543.                                         - 7 -
  544.  
  545.  
  546.  
  547.  
  548.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  549.  
  550.                would have the value 7, and s.S[1] through s.S[7] would hold
  551.                the  bits.   The number 7 is computed on the assumption that
  552.                the type _u_n_s_i_g_n_e_d _s_h_o_r_t on the target host  is  sufficiently
  553.                large  to  holds  16  bits.  The set operators of Pascal are
  554.                implemented as C functions returning pointers to  arrays  of
  555.                setwords, the intermediary results are held in a static area
  556.                of fixed size.
  557.  
  558.           -    Pascal files are implemented using the standard i/o  package
  559.                availible  in  most C implementations.  Since Pascal has the
  560.                requirement that the next element of a file  is  visible  in
  561.                the  filebuffer  before it is read, and the requirement that
  562.                linemarkers in textfiles are given special treatement we are
  563.                forced  to  extend  the  _F_I_L_E  type  provided  in <_s_t_d_i_o._h>.
  564.                Hence:
  565.  
  566.                        var   f  : text;
  567.  
  568.                becomes
  569.  
  570.                        typedef struct {
  571.                           FILE  *fp;
  572.                           unsigned short
  573.                                 eoln:1,
  574.                                 eof:1,
  575.                                 init:1,
  576.                                 out:1,
  577.                                 :12;
  578.                           char  buf;
  579.                        }  text;
  580.                        text  f;
  581.  
  582.                where _b_u_f is our filebuffer and _e_o_l_n, _e_o_f and _i_n_i_t are flags
  583.                giving the state of the file.  All Pascal i/o operations are
  584.                implemented using macros that maintain  the  flags  and  the
  585.                buffer  variable.  The actual reading and writing of data is
  586.                deferred to the standard i/o package.
  587.  
  588.           _3._3._4.  _P_r_o_c_e_d_u_r_e_s _a_n_d _f_u_n_c_t_i_o_n_s
  589.  
  590.           Pascal  procedures  and  functions  are  somewhat  difficult   to
  591.           translate to C.  The main problems lie in nested declarations and
  592.           procedural parameters.  Nested declarations are  handled  in  the
  593.           following manner:
  594.  
  595.                -    If procedure B is declared in procedure  A,  then  pro-
  596.                     cedure  B is emitted before A and A is forward declared
  597.                     before B.
  598.  
  599.                -    Any constants and types declared in A is moved  to  the
  600.                     global scope, this may force renaming of those objects.
  601.  
  602.                -    Any variable declared in A _a_n_d _u_s_e_d _i_n _B  is  converted
  603.                     to  a  pointer  and  moved  to  the  global scope.  The
  604.                     pointer value is saved  and  re-initialized  upon  each
  605.                     entry of A and restored upon exit from A.
  606.  
  607.  
  608.  
  609.  
  610.  
  611.                                         - 8 -
  612.  
  613.  
  614.  
  615.  
  616.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  617.  
  618.           Hence:
  619.  
  620.                   procedure A;
  621.  
  622.                   const limit = 20;
  623.  
  624.                   type  loctyp   = 0 .. limit;
  625.  
  626.                   var   i, j  : loctyp;
  627.  
  628.                      procedure B(k : loctyp);
  629.  
  630.                      begin
  631.                         j := k + 2
  632.                      end;
  633.  
  634.                   begin
  635.                      B(i)
  636.                   end;
  637.  
  638.           becomes
  639.  
  640.                   typedef unsigned char   loctyp;
  641.                   loctyp   *G56_j;
  642.  
  643.                   void a();
  644.  
  645.                    void
  646.                   b(k)
  647.                      loctyp  k;
  648.                   {
  649.                      (*G56_j) = k + 2;
  650.                   }
  651.  
  652.                    void
  653.                   a()
  654.                   {
  655.                   # define limit 20
  656.                      loctyp  i, j;
  657.                      loctyp  *F57;
  658.  
  659.                      F57 = G56_j;
  660.                      G56_j = &j;
  661.                      b(i);
  662.                      G56_j = F57;
  663.                   }
  664.  
  665.           we see that references to _j inside procedure _b  are  replaced  by
  666.           the  pointer  _G_5_6__j  which points to the local variable _j in pro-
  667.           cedure _a.  In order to preserve the proper semantix in  the  face
  668.           of  recursion  the value of the pointer need also be saved in the
  669.           local variable _F_5_7 during the invocation of _a.
  670.  
  671.           -    Procedure parameters offer little  problems.   We  translate
  672.                Pascal  value-parameters into ordinary C parameters and Pas-
  673.                cal var-parameters are treated as pointers.
  674.  
  675.  
  676.  
  677.  
  678.  
  679.                                         - 9 -
  680.  
  681.  
  682.  
  683.  
  684.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  685.  
  686.           -    Procedural parameters appear at first to be easy to  handle.
  687.                The ordinary program:
  688.  
  689.                        program p;
  690.  
  691.                        procedure pp(procedure q(i : integer));
  692.  
  693.                        begin
  694.                           q(2)
  695.                        end;
  696.  
  697.                        procedure qq(i : integer);
  698.                        begin
  699.                        end;
  700.  
  701.                        begin
  702.                           pp(qq)
  703.                        end.
  704.  
  705.                becomes
  706.  
  707.                        extern void exit();
  708.                        typedef int integer;
  709.  
  710.                         void
  711.                        pp(q)
  712.                           void  (*q)();
  713.                        {
  714.                           (*q)(2);
  715.                        }
  716.  
  717.                         void
  718.                        qq(i)
  719.                           integer i;
  720.                        {
  721.                        }
  722.  
  723.                        main()
  724.                        {
  725.                           pp(qq);
  726.                           exit(0);
  727.                        }
  728.  
  729.                which looks simple enough.
  730.                However, Pascal requires  that  the  scope  of  a  procedure
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.                                        - 10 -
  748.  
  749.  
  750.  
  751.  
  752.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  753.  
  754.                _r_e_m_a_i_n_s _u_n_c_h_a_n_g_e_d throughout its lifetime.  Consider:
  755.  
  756.                        program demo(output);
  757.  
  758.                        var   i  : integer;
  759.  
  760.                           procedure p(procedure q);
  761.  
  762.                           var   j  : integer;
  763.  
  764.                              procedure qq;
  765.  
  766.                              begin
  767.                                 writeln(j)
  768.                              end;
  769.  
  770.                           begin
  771.                              j := i;
  772.                              q;
  773.                              if i < 1 then
  774.                                begin
  775.                                 i := i + 1;
  776.                                 p(qq)
  777.                                end
  778.                           end;
  779.  
  780.                           procedure dummy;
  781.                           begin
  782.                           end;
  783.  
  784.                        begin
  785.                           i := 0;
  786.                           p(dummy)
  787.                        end.
  788.  
  789.                When _p is first invoked it assigns the local variable _j  the
  790.                value  0.   This  variable  is  accessible  from _q_q which is
  791.                passed as a parameter in  the  recursive  call  of  _p.   The
  792.                second  invocation  of  _p then sets _i_t_s variable _j to 1, and
  793.                calls _q which is bound to the  first  instance  of  _q_q,  and
  794.                should  therefore  print the number _0.  _S_a_d_l_y, _t_h_e _c_o_d_e _p_r_o_-
  795.                _d_u_c_e_d _b_y _t_h_e _t_r_a_n_s_l_a_t_o_r _f_a_i_l_s _t_o _d_o  _t_h_i_s.   It  is  obvious
  796.                that  the  program  above calls for a complete simulation of
  797.                the activation record mechanism of Pascal to work correctly.
  798.  
  799.                A workable but unpractical solution would be:
  800.  
  801.                1)   When qq is used as parameter  we  call  a  function  q1
  802.                     which saves the environment for qq (i.e. the address of
  803.                     j) in a well known place and returns a pointer to q2.
  804.  
  805.                2)   When qq is later called (under the name q)  the  actual
  806.                     target  will be q2 which sets up the proper environment
  807.                     calls qq.
  808.  
  809.                The problem is that this requires a save-area for _e_a_c_h  pro-
  810.                cedural parameter which can hold the intresting parts of its
  811.                environment for _e_a_c_h of its  invocations.   In  the  example
  812.                above  we need one are which holds the address of i for each
  813.  
  814.  
  815.  
  816.  
  817.                                        - 11 -
  818.  
  819.  
  820.  
  821.  
  822.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  823.  
  824.                instance of qq (say N instances,  where  N  depends  on  the
  825.                run-time  behaviour  of  p).  It also requires a set of dif-
  826.                ferent procedures to perform the work  of  q2  (N  different
  827.                procedures   which   sets  up  the  environment  for  the  N
  828.                instances).  _T_h_i_s _r_e_q_u_i_r_e_s _m_u_c_h _t_o _m_u_c_h _w_o_r_k _t_o _i_m_p_l_e_m_e_n_t _s_o
  829.                _t_h_e  _p_r_o_b_l_e_m  _i_s  _l_e_f_t _u_n_s_o_l_v_e_d, this is hardly a problem in
  830.                practice since humans rarely write such code  but  _i_t  _c_o_u_l_d
  831.                _i_n_t_r_o_d_u_c_e _p_r_o_b_l_e_m_s in machine generated Pascal code.
  832.  
  833.                It should be noted that the translator accepts  the  keyword
  834.                _e_x_t_e_r_n_a_l  in  place  of  the  Pascal  _f_o_r_w_a_r_d  directive and
  835.                assumes that the so declared procedure is defined elsewhere.
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.                                        - 12 -
  886.  
  887.  
  888.  
  889.  
  890.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  891.  
  892.           _3._4.  _S_t_a_t_e_m_e_n_t_s.
  893.  
  894.           Pascal statements are comparatively easy to translate to C.   The
  895.           only parts that require special care are non-local _g_o_t_o, _w_i_t_h and
  896.           _f_o_r statements.  The code
  897.  
  898.                   program p(output);
  899.  
  900.                   type
  901.                      msgtyp   = packed array [ 1 .. 12 ] of char;
  902.  
  903.                   var
  904.                      a  : array [ 1 .. 10 ] of
  905.                            record
  906.                               r  : real
  907.                            end;
  908.                      i  : integer;
  909.                      ok : boolean;
  910.  
  911.                      procedure fatal(m : msgtyp);
  912.  
  913.                      begin
  914.                         writeln('Fatal error: ', m)
  915.                      end;
  916.  
  917.                   begin
  918.                      while true do
  919.                        repeat
  920.                         ok := false;
  921.                         i := 1;
  922.                         for i := i + 1 to i + 10 do
  923.                            if i > 10 then
  924.                               fatal(' 10 exceeded')
  925.                            else
  926.                              with a[i] do
  927.                               if r > 9.99e+38 then
  928.                                  ok := true
  929.                               else
  930.                                  writeln(r)
  931.                        until ok
  932.                   end.
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.                                        - 13 -
  954.  
  955.  
  956.  
  957.  
  958.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  959.  
  960.           becomes
  961.  
  962.                   typedef char boolean;
  963.                   # define false (boolean)0
  964.                   # define true (boolean)1
  965.                   typedef int integer;
  966.                   typedef double real;
  967.  
  968.                   typedef struct { char A[12 - 1 + 1]; } msgtyp;
  969.                   typedef struct { struct S57 {
  970.                      real  r;
  971.                   }  A[10 - 1 + 1]; }  T56;
  972.                   T56      a;
  973.                   integer  i;
  974.                   boolean  done;
  975.  
  976.                    void
  977.                   fatal(m)
  978.                      msgtyp   m;
  979.                   {
  980.                      (void)fprintf(output.fp, "Fatal error: %.12s", m.A),
  981.                                  Putchr('\n', output);
  982.                   }
  983.  
  984.                   main()
  985.                   {
  986.                      while (true)
  987.                        do {
  988.                         done = false;
  989.                         i = 1;
  990.                         {
  991.                           integer      B1 = i + 1, B2 = i + 10;
  992.  
  993.                           if (B1 <= B2)
  994.                            for (i = B1; ; i++) {
  995.                               if (i > 10)
  996.                                  fatal(*((msgtyp *)" 10 exceeded"));
  997.                               else {
  998.                                  register struct   S57 *W3 = &a.A[i - 1];
  999.  
  1000.                                  if (W3->r > 9.99e+38)
  1001.                                     done = true;
  1002.                                  else
  1003.                                     (void)fprintf(output.fp, "% 20e", W3->r),
  1004.                                        Putchr('\n', output);
  1005.                               }
  1006.                               if (i == B2) break;
  1007.                            }
  1008.                         }
  1009.                        } while (!(done));
  1010.                      exit(0);
  1011.                   }
  1012.  
  1013.           for the following reasons:
  1014.  
  1015.           _3._4._1.  _B_e_g_i_n
  1016.  
  1017.           The compound statements are very similar in the two languages and
  1018.           need no further explanation.
  1019.  
  1020.  
  1021.  
  1022.  
  1023.                                        - 14 -
  1024.  
  1025.  
  1026.  
  1027.  
  1028.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1029.  
  1030.           _3._4._2.  _I_f
  1031.  
  1032.           Pascal if-statements have the same structure and  semantix  as  C
  1033.           if-statments.
  1034.  
  1035.           _3._4._3.  _C_a_s_e
  1036.  
  1037.           Pascal case-statements have the same structure and semantix as  C
  1038.           switch-statements  provided  that a _b_r_e_a_k is always added to each
  1039.           entry.
  1040.  
  1041.           The translator supports a common  Pascal  extension  in  that  it
  1042.           recognizes  the keyword _o_t_h_e_r_w_i_s_e to signify a default entry in a
  1043.           case-statement.
  1044.  
  1045.           _3._4._4.  _L_a_b_e_l_s
  1046.  
  1047.           Pascal labeled statements and labels have the same structure  and
  1048.           semantix  as  C  labeled statements except that Pascal labels are
  1049.           numbers where C labels are identifiers, this difference is solved
  1050.           by simply prefixing the labels with the letter _L.
  1051.  
  1052.           _3._4._5.  _G_o_t_o
  1053.  
  1054.           Pascal goto-statements have the same structure as C  goto  state-
  1055.           ments  but  the  semantix  differ in that Pascal allows a goto to
  1056.           lead out of the current procedure.  This is implemented using the
  1057.           _s_e_t_j_m_p/_l_o_n_g_j_m_p library functions of C as described earlier.
  1058.  
  1059.           _3._4._6.  _W_i_t_h
  1060.  
  1061.           The with-statement of Pascal has no  counterpart  in  C.   It  is
  1062.           translated into nested compund statements where pointervariables,
  1063.           referencing the corresponding records, are declared and  initial-
  1064.           ized.   Within  the  scope  of the with-statement, the accessible
  1065.           record fields are renamed to include the pointer.  The effect  of
  1066.           this  is  that the record address is evaluated once as the Pascal
  1067.           standard requires.
  1068.  
  1069.           _3._4._7.  _F_o_r
  1070.  
  1071.           The for-statement of Pascal has a structure that  is  similar  to
  1072.           the  C  for-statement but the semantix differ completely.  Pascal
  1073.           requires that a loop be exited when  the  upper  bound  has  been
  1074.           reached,   Pascal  also  requires  that  the  loop-boundaries  be
  1075.           evaluated exactly once.  The standard C for-loop is  exited  when
  1076.           the  loop-condition  becomes  false.  This implies that it is not
  1077.           always true that
  1078.  
  1079.                   for (i = 0; i <= e; i++) ;
  1080.  
  1081.           behaves in the same manner as
  1082.  
  1083.                   for i := 0 to e do ;
  1084.  
  1085.           since (in most implementations) the C version becomes an infinite
  1086.           loop  if  _e  equals _m_a_x_i_n_t or if _e is the expression _i.  For that
  1087.           reason Pascal for-statments are translated into  compound  state-
  1088.           ments  where  the  upper/lower bounds of the for-loop are held in
  1089.  
  1090.  
  1091.  
  1092.  
  1093.                                        - 15 -
  1094.  
  1095.  
  1096.  
  1097.  
  1098.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1099.  
  1100.           local variables.  It is  also  necessary  to  add  a  conditional
  1101.           break-statement at the end of the loop.  It is possible to obtain
  1102.           the  more  relaxed  translation  by  configuring  the  translator
  1103.           appropriately (see "Tuning" below).
  1104.  
  1105.           _3._4._8.  _W_h_i_l_e
  1106.  
  1107.           The while-statement behaves exactly the same in both languages.
  1108.  
  1109.           _3._4._9.  _R_e_p_e_a_t
  1110.  
  1111.           The repeat-statement of Pascal matches the do-while statement  of
  1112.           C  except  for  the  trivial  difference  that  Pascal  permits a
  1113.           statement-list where C permits a single statment in the loop.
  1114.  
  1115.           _3._4._1_0.  _E_m_p_t_y
  1116.  
  1117.           The empty statement has (of course) the same structure and seman-
  1118.           tix in both languages.
  1119.  
  1120.           _3._5.  _E_x_p_r_e_s_s_i_o_n_s _a_n_d _a_s_s_i_g_n_m_e_n_t_s
  1121.  
  1122.           In most cases Pascal expressions can be literally translated into
  1123.           equivalent C expressions.
  1124.  
  1125.           identifiers    Except where identifiers clash with reserved words
  1126.                          or  with  other  identifiers  declared in the same
  1127.                          scope, they may simply be printed.  In some  cases
  1128.                          the  translator is forced to rename identifiers or
  1129.                          to invent new identifiers.
  1130.  
  1131.           operators      The operators +, -, * _d_i_v and _m_o_d when applied  to
  1132.                          real  or  integer operands have exact counterparts
  1133.                          in C and are therefore easy to handle.  The opera-
  1134.                          tor  for real division, /, corresponds to the same
  1135.                          C  operator  except  that  the  operands  may   be
  1136.                          integers.  In that case a cast is necessary.  When
  1137.                          the operands are sets the expression is  converted
  1138.                          into a function call.
  1139.  
  1140.                          The operators <, <=, >, >=,  =  and  <>  all  have
  1141.                          exact  counterparts  in  C  for  integer  and real
  1142.                          operands.  Most C implementations  disallows  _e_n_u_m
  1143.                          operands,  the  translator  therefore  casts  such
  1144.                          operands to _i_n_t.  Comparisons on structures  (i.e.
  1145.                          strings  or  sets)  are  converted  into  function
  1146.                          calls.
  1147.  
  1148.           assignments    Assignments are straightforward  to  handle  since
  1149.                          arrays are encapsulated in structures.  Therefore:
  1150.  
  1151.                                  a := b
  1152.  
  1153.                          becomes
  1154.  
  1155.                                  a = b
  1156.  
  1157.                          _u_n_l_e_s_s b is a string or a set, in which  case  the
  1158.                          assignment is converted into a function call.
  1159.  
  1160.  
  1161.  
  1162.  
  1163.                                        - 16 -
  1164.  
  1165.  
  1166.  
  1167.  
  1168.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1169.  
  1170.           indexing       Given  the  translation  for  array   declarations
  1171.                          (described above) we are forced to translate
  1172.  
  1173.                                  a[i]
  1174.  
  1175.                          into
  1176.  
  1177.                                  a.A[i - c]
  1178.  
  1179.                          where _c is the lower bound for the index type.
  1180.  
  1181.           selection      Given the translation for  records  with  variants
  1182.                          (described above) the translation of
  1183.  
  1184.                                  a.b
  1185.  
  1186.                          becomes
  1187.  
  1188.                                  a.b
  1189.  
  1190.                          _o_r, if b is declared in a variant,
  1191.  
  1192.                                  a.Vxxx.b
  1193.  
  1194.                          where Vxxx is a name manufactured by the  transla-
  1195.                          tor for the particular variant.
  1196.  
  1197.           dereferencing  Pointer references and _v_a_r-parameters are  handled
  1198.                          by  prefixing the expression with an asterisk, but
  1199.                          the special case dereferencing followed by  selec-
  1200.                          tion is also recognized, so:
  1201.  
  1202.                                  p^ := q^.f
  1203.  
  1204.                          becomes
  1205.  
  1206.                                  *p = q->f
  1207.  
  1208.  
  1209.           miscellanea    The boolean operators _a_n_d, _o_r and _n_o_t  are  simply
  1210.                          translated  into  their  C  counterparts.  The set
  1211.                          contructors [], and ..  and the  operator  _i_n  are
  1212.                          converted to function calls.
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.                                        - 17 -
  1232.  
  1233.  
  1234.  
  1235.  
  1236.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1237.  
  1238.           _4.  _I_m_p_l_e_m_e_n_t_a_t_i_o_n
  1239.  
  1240.           The general strategy is to convert the Pascal source program into
  1241.           a  parsetree.   The tree is then traversed by a set of procedures
  1242.           that perform some necessary transformations.  The tree is finally
  1243.           traversed  by  a set of procedures that print the corresponding C
  1244.           constructs.  The translator consists of  three  major  procedures
  1245.           that  perform these actions.  They are augmented by a set of pro-
  1246.           cedures that maintain a symbol table that holds information about
  1247.           identifiers found in the source, and by a procedure that initial-
  1248.           izes all internal datastructures.
  1249.  
  1250.           There are three major datastructures that interact in complicated
  1251.           ways:
  1252.  
  1253.           1)   a store for identifiers and strings
  1254.  
  1255.           2)   a multilevel symbol table
  1256.  
  1257.           3)   a parse-tree.
  1258.  
  1259.           The identifier and string store, _s_t_r_s_t_o_r is in principle an array
  1260.           of  characters  that  grow  in  increments  of  one string block.
  1261.           Exactly one copy of each identifier  is  stored  in  that  array.
  1262.           Whenever  an identifier is found in the input stream the array is
  1263.           scanned to see if that identifier has been seen before.  In order
  1264.           to  speed  up the search all identifiers are represented by nodes
  1265.           which are chained together such that all nodes  in  a  particular
  1266.           chain have the same hashvalue as determined by the function _h_a_s_h.
  1267.           Each _i_d_n_o_d_e holds an index to  strstor  where  the  corresponding
  1268.           identifier text is stored.  The start of the hashchains are found
  1269.           in the global variable _i_d_t_a_b.
  1270.  
  1271.           idtab
  1272.           +----+
  1273.           |  |  chain of idnodes with same hashvalue
  1274.           +----+  +--------+  +--------+
  1275.           |  |----->|     |----->|     |idnode representing
  1276.           +----+  |     |   index=2|     |identifier "demo"
  1277.           |  |  +--------+  +--------+
  1278.  
  1279.              strstor
  1280.           +------------ - --------+
  1281.           |  |  |     |  |
  1282.           +------------ - --------+|
  1283.             |
  1284.  
  1285.           +--------------------------------
  1286.           |  |  |d |e |m |o |/ |
  1287.           +--------------------------------   first idblock
  1288.                  |^
  1289.                 index=2
  1290.  
  1291.  
  1292.           So: the global representation of the identifier "demo" is a  par-
  1293.           ticlular idnode; whenever the lexical analysis routine recognizes
  1294.           the identifier "demo" it returns a pointer to that idnode.
  1295.  
  1296.  
  1297.  
  1298.  
  1299.                                        - 18 -
  1300.  
  1301.  
  1302.  
  1303.  
  1304.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1305.  
  1306.           In order to represent different identifiers with the same name we
  1307.           need  to  be  able to distinguish between identifiers declared in
  1308.           different scopes.  This is accomplished  by  the  _s_y_m_n_o_d_e  struc-
  1309.           tures.   When an identifier is first encountered in a given scope
  1310.           it is "declared", meaning that a  new  symnode  is  created  that
  1311.           references the identifier.  Occurrences of the same identifier in
  1312.           that scope are then represented in the  parse-tree  by  treenodes
  1313.           referencing the same symnode.
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333.  
  1334.  
  1335.  
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.  
  1342.  
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.                                        - 19 -
  1368.  
  1369.  
  1370.  
  1371.  
  1372.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1373.  
  1374.           The program:
  1375.  
  1376.                   program p;
  1377.  
  1378.                   var   demo  : integer;
  1379.  
  1380.                   begin
  1381.                      demo := 3
  1382.                   end.
  1383.  
  1384.           yilds the following structure:
  1385.  
  1386.              top
  1387.  
  1388.              +----------------+treenode representing
  1389.               npgm|           |the program
  1390.              +----|-----|-----|-----+
  1391.                 |  | |^| |^
  1392.                 |  | || +-----------------------------+
  1393.                 |  | |+----------------------------+ |
  1394.                 |    |                     | |
  1395.                 | +-----|-------+treenode representing| |
  1396.                 |  nvar|      |the var-declaration|
  1397.                 | +---|----|-----+        +---------------|---+treenode repr.
  1398.                 |  | |^|            nassign|           |assignment
  1399.                 |  | |+-------> to type+----|---------|-----+
  1400.           symtab|    |                 |^     |^
  1401.           +----+  | +-----|---+treenode repr.+-------|---+ +-----|-------+
  1402.           |  |<------+  nid|   |occurrence ofnid|     |  ninteger|      |
  1403.                   +--|-----+id. "demo" +----|-----+ +------|-----+
  1404.           |  |     | |^               |        | |^
  1405.           +----+     | |+--------------------+        | |
  1406.           |  |       |                          |
  1407.           +----+  +-------|-------+symnode representing+-------|------+
  1408.           |  |----->    lidentifier|        |identifier "demo" linteger|       |
  1409.           +----+  +----|---------+in the current scopelinum=3|       |
  1410.                    |                       +-----------+
  1411.           idtab    +------------+
  1412.           +----+              |
  1413.           |  |
  1414.           +----+  +--------+  +--------+
  1415.           |  |----->|     |----->|     |idnode representing
  1416.           +----+  |     |   index=2|     |identifier "demo"
  1417.           |  |  +--------+  +--------+
  1418.  
  1419.              strstor
  1420.           +------------ - --------+
  1421.           |  |  |     |  |
  1422.           +---|----------- - --------+
  1423.             |
  1424.  
  1425.           +--------------------------------
  1426.           |  |  |d |e |m |o |/ |
  1427.           +--------------------------------   first idblock
  1428.                  |^
  1429.                 index=2
  1430.  
  1431.           We see that the two occurrences  of  the  identifier  "demo"  are
  1432.           represented  by  two  _t_r_e_e_n_o_d_e_s  of  variant  _n_i_d  that both have
  1433.  
  1434.  
  1435.  
  1436.  
  1437.                                        - 20 -
  1438.  
  1439.  
  1440.  
  1441.  
  1442.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1443.  
  1444.           pointers to the same  _s_y_m_n_o_d_e  representing  the  declaration  of
  1445.           "demo".   All  symnodes  at  a given declarationlevel are chained
  1446.           together (in the same manner as the idnodes) and the  chains  are
  1447.           attached  to the global variable _s_y_m_t_a_b.  In order to find out if
  1448.           an identifer is declared in the current scope we scan  the  chain
  1449.           of symnodes starting from symtab, and check if any of them refer-
  1450.           ences the idnode we are looking  for.   A  symnode  also  have  a
  1451.           pointer  to  the  treenode which defines the symbol.  The _s_y_m_t_a_b_s
  1452.           themselves are also chained, the  chain  implements  a  stack  of
  1453.           declarationlevels.  The symtab which is created when the scope of
  1454.           a procedure is entered is also attached to that procedure.   When
  1455.           a  procedure  is entered we create a new symtab, push it onto the
  1456.           stack, parse the procedure and pop the stack.  The  symbols  then
  1457.           visible are those that still can be reached from the stack.
  1458.  
  1459.           The parse-tree consists of _t_r_e_e_n_o_d_e_s representing  each  declara-
  1460.           tion,  statement,  expression etc.  Each node except the nprogram
  1461.           node has a pointer to its immediate father (giving  the  defining
  1462.           point),  to its children (if it has any) and to its right brother
  1463.           (if it is a member of a list).  The top of the tree is  found  in
  1464.           the global variable _t_o_p.
  1465.  
  1466.           In order to find the defining point for  the  identifier  in  the
  1467.           assignment,  we  follow pointers from the nassign-treenode to the
  1468.           nid-treenode, to the lidentifier-symnode,  and  then  up  to  the
  1469.           nid-treenode  in the declaration.  If we want to know the type of
  1470.           the identifier we proceed up to the nvar-treenode and  then  down
  1471.           to  the  node  giving the type in the declaration (in our example
  1472.           that node would also be a nid-treenode  referencing  a  linteger-
  1473.           symnode  that  represents  the identifier "integer").  There is a
  1474.           function _t_y_p_e_o_f that performs exactly this  operation.   It  will
  1475.           return  a  pointer  to  a  npredef-,  nsubrange-, nscalar-, nptr-
  1476.           narray-, nrecord-, nfileof- or nsetof-treenode.  In  those  cases
  1477.           where  the  translator  pays attention to types it uses a pointer
  1478.           (obtained from typeof) as representation of a type.
  1479.  
  1480.           Given the parse-tree and the layered symbol table it is not  hard
  1481.           to see how the translations described earlier are performed.  The
  1482.           one place where the code becomes more  than  usually  complex  is
  1483.           when  a  _w_r_i_t_e  statement  with  format  specifications  is to be
  1484.           translated into a call to _f_p_r_i_n_t_f.
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.                                        - 21 -
  1506.  
  1507.  
  1508.  
  1509.  
  1510.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1511.  
  1512.           _5.  _T_u_n_i_n_g
  1513.  
  1514.           The behaviour of the translator may be modified  for  some  cases
  1515.           simply by changing constants.  These constants are all located at
  1516.           the top of the program text.
  1517.  
  1518.           output      The translator will copy the source during  input  if
  1519.                       the  constant _e_c_h_o is true.  The copy is preceeded by
  1520.                       the line
  1521.  
  1522.                               # ifdef PASCAL
  1523.  
  1524.                       and ended by the line
  1525.  
  1526.                               # else
  1527.  
  1528.                       and then follows the translated code and finally
  1529.  
  1530.                               # endif
  1531.  
  1532.                       This may be used to hold both Pascal and C source  in
  1533.                       the  same  file.  If the Pascal part is changed the C
  1534.                       part may be updated through:
  1535.  
  1536.                                  cpp -P -DPASCAL < orig > tmp
  1537.                                  ptc < tmp > new
  1538.                                  move new orig
  1539.  
  1540.                       assuming that _e_c_h_o is true and that _c_p_p is the  stan-
  1541.                       dard C preprocessor.
  1542.  
  1543.                               Default value:
  1544.  
  1545.                                  echo     = false;
  1546.  
  1547.  
  1548.           comments    The translator recognizes both (* and  {  as  comment
  1549.                       delimiters.   They are treated as different, allowing
  1550.                       1 level nested comments, if the constant  _d_i_f_f_c_o_m  is
  1551.                       true.
  1552.  
  1553.                               Default value:
  1554.  
  1555.                                  diffcomm = false;
  1556.  
  1557.  
  1558.           symbols     The  translator  accepts  default  entries  in  case-
  1559.                       statements  provided that the keyword defined through
  1560.                       _o_t_h_e_r_s_y_m is used in place of the constant list.
  1561.  
  1562.                               Default value:
  1563.  
  1564.                                  othersym = 'otherwise ';
  1565.  
  1566.                       substitute for
  1567.  
  1568.                                  othersym = 'otherwise%';
  1569.  
  1570.                       if that feature is undesired.
  1571.  
  1572.  
  1573.  
  1574.  
  1575.                                        - 22 -
  1576.  
  1577.  
  1578.  
  1579.  
  1580.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1581.  
  1582.                       The translator accepts externally declared procedures
  1583.                       and  functions  provided  that  the directive defined
  1584.                       through _e_x_t_e_r_n_s_y_m is used in  place  of  the  keyword
  1585.                       _f_o_r_w_a_r_d.
  1586.  
  1587.                               Default value:
  1588.  
  1589.                                  externsym   = 'external  ';
  1590.  
  1591.  
  1592.           sets        Sets are implemented as arrays of _w_o_r_d_t_y_p_e.  The type
  1593.                       is assumed to hold _s_e_t_b_i_t_s + _1 bits numbered from 0.
  1594.  
  1595.                               Default value:
  1596.  
  1597.                                  wordtype = 'unsigned short';
  1598.                                  setbits  = 15;
  1599.  
  1600.  
  1601.           files       The implementation of files uses  a  flag-word  which
  1602.                       has  the  type  given as _f_i_l_e_b_i_t_s which is assumed to
  1603.                       hold _f_i_l_e_f_i_l_l + _4 bits.
  1604.  
  1605.                               Default value:
  1606.  
  1607.                                  filebits = 'unsigned short';
  1608.                                  filefill = 12;
  1609.  
  1610.  
  1611.           stmts       If the Pascal source is known to be "normal"  in  the
  1612.                       sense  that for-loops always have an upper bound that
  1613.                       is less than the maximum value of  the  type  of  the
  1614.                       loop-variable,  and in the sense that the upper bound
  1615.                       doesn't change by computations inside the loop,  then
  1616.                       the  translator  may  generate  a  more natural code.
  1617.                       I.e:
  1618.  
  1619.                               for i := 1 to 10 do ;
  1620.  
  1621.                       becomes
  1622.  
  1623.                               for (i = 1; i <= 10; i++) ;
  1624.  
  1625.                       Since the requirements cannot be  determined  by  the
  1626.                       translator itself this kind of code is generated when
  1627.                       the constant _l_a_z_y_f_o_r is true.
  1628.  
  1629.                               Default value:
  1630.  
  1631.                                  lazyfor  = false;
  1632.  
  1633.  
  1634.  
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.                                        - 23 -
  1644.  
  1645.  
  1646.  
  1647.  
  1648.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1649.  
  1650.           new         The second and following parameters to the  procedure
  1651.                       _n_e_w  will  be  ignored  if  the  constant _u_n_i_o_n_n_e_w is
  1652.                       false.
  1653.  
  1654.                               Default value:
  1655.  
  1656.                                  unionnew = true;
  1657.  
  1658.  
  1659.           strings     All identifiers and strings are stored in the  trans-
  1660.                       lator  with  the special character having the ordinal
  1661.                       value _n_u_l_l as endmarker.  Hence, that  character  can
  1662.                       not occur in strings in the Pascal source.
  1663.  
  1664.                               Default value:
  1665.  
  1666.                                  null     = 0;
  1667.  
  1668.  
  1669.           types       The names of predefined types are given by  the  con-
  1670.                       stants: _i_n_t_t_y_p, _c_h_a_r_t_y_p, _f_l_o_a_t_t_y_p, and _d_o_u_b_l_e_t_y_p.
  1671.  
  1672.                               Default value:
  1673.  
  1674.                                  inttyp      = 'int';
  1675.                                  chartyp  = 'char';
  1676.                                  floattyp = 'float';
  1677.                                  doubletyp   = 'double';
  1678.  
  1679.                       The typename for real variables and functions defined
  1680.                       by the user is given by the constant _r_e_a_l_t_y_p.
  1681.  
  1682.                               Default value:
  1683.  
  1684.                                  realtyp  = doubletyp;
  1685.  
  1686.                       The typename for procedures is given by the  constant
  1687.                       _v_o_i_d_t_y_p.
  1688.  
  1689.                               Default value:
  1690.  
  1691.                                  voidtyp  = 'void';
  1692.  
  1693.  
  1694.           i/o         The default fieldwidths for integer and  real  values
  1695.                       written  on  textfiles  are  given  by  the constants
  1696.                       _i_n_t_l_e_n and _f_i_x_l_e_n.
  1697.  
  1698.                               Default value:
  1699.  
  1700.                                  intlen   = 10;
  1701.                                  fixlen   = 20;
  1702.  
  1703.  
  1704.           types       A table in the translator gives the mapping from Pas-
  1705.                       cal  integer  subrange  types  to C arithmetic types.
  1706.                       The table is initialized by code located at  the  end
  1707.                       of  procedure _i_n_i_t_i_a_l_i_z_e giving the following default
  1708.                       configuration:
  1709.  
  1710.  
  1711.  
  1712.  
  1713.                                        - 24 -
  1714.  
  1715.  
  1716.  
  1717.  
  1718.           Holistic Technology AB         PTC            HD870410-1 Rev: 1.6
  1719.  
  1720.                       Low bound     High bound   Selected type
  1721.  
  1722.                                 0          255   unsigned char
  1723.                              -128          127   char
  1724.                                 0        65535   unsigned short
  1725.                            -32768        32767   short
  1726.                       -2147483647   2147483647   long
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751.  
  1752.  
  1753.  
  1754.  
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.                                        - 25 -
  1782.  
  1783.  
  1784.